package com.bcntouch.touch2act.NFC;

import java.nio.charset.Charset;
import java.util.Arrays;

import android.net.Uri;
import android.nfc.NdefRecord;

public class UriNdefRecord {
	public static final String RECORD_TYPE = "UriNdefRecord";

    public static final String[] URI_PREFIX_MAP = {
        "",
        "http://www.",
        "https://www.",
        "http://",
        "https://",
        "tel:",
        "mailto:",
        "ftp://anonymous:anonymous@",
        "ftp://ftp.",
        "ftps://",
        "sftp://",
        "smb://",
        "nfs://",
        "ftp://",
        "dav://",
        "news:",
        "telnet://",
        "imap:",
        "rtsp://",
        "urn:",
        "pop:",
        "sip:",
        "sips:",
        "tftp:",
        "btspp://",
        "btl2cap://",
        "btgoep://",
        "tcpobex://",
        "irdaobex://",
        "file://",
        "urn:epc:id:",
        "urn:epc:tag:",
        "urn:epc:pat:",
        "urn:epc:raw:",
        "urn:epc:",
        "urn:nfc:",
    };

    private final Uri mUri;

    private UriNdefRecord(Uri uri) {
        this.mUri = uri;
    }

    public Uri getUri() {
        return mUri;
    }

    /**
     * Convert {@link android.nfc.NdefRecord} into a {@link android.net.Uri}.
     * This will handle both TNF_WELL_KNOWN / RTD_URI and TNF_ABSOLUTE_URI.
     *
     * @throws IllegalArgumentException if the NdefRecord is not a record
     *         containing a URI.
     */
    public static UriNdefRecord parse(NdefRecord record) {
        short tnf = record.getTnf();
        if (tnf == NdefRecord.TNF_WELL_KNOWN) {
            return parseWellKnown(record);
        } else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) {
            return parseAbsolute(record);
        }
        throw new IllegalArgumentException("Unknown TNF " + tnf);
    }

    /** Parse and absolute URI record */
    private static UriNdefRecord parseAbsolute(NdefRecord record) {
        byte[] payload = record.getPayload();
        Uri uri = Uri.parse(new String(payload, Charset.forName("UTF-8")));
        return new UriNdefRecord(uri);
    }

    /** Parse an well known URI record */
    private static UriNdefRecord parseWellKnown(NdefRecord record) {
    	if ( ! Arrays.equals( NdefRecord.RTD_URI, record.getType() ) )
    		throw new IllegalArgumentException( "Incorrect Record Type" );
    	
        byte[] payload = record.getPayload();
        /*
         * payload[0] contains the URI Identifier Code, per the
         * NFC Forum "URI Record Type Definition" section 3.2.2.
         *
         * payload[1]...payload[payload.length - 1] contains the rest of
         * the URI.
         */
        int i = payload[0];
        if ( i >= URI_PREFIX_MAP.length ) {
        	throw new IllegalArgumentException( "Incorrect Record Type prefix " + i );
        }
        String prefix = URI_PREFIX_MAP[ payload[0] ];
        byte[] fullUri = Bytes.concat(prefix.getBytes(Charset.forName("UTF-8")), Arrays.copyOfRange(payload, 1, payload.length));
        Uri uri = Uri.parse(new String(fullUri, Charset.forName("UTF-8")));
        return new UriNdefRecord(uri);
    }

    public boolean hasUri() {
    	return true;
    }
    
    public static boolean isUri(NdefRecord record) {
        try {
            parse(record);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
    
    public String toString() {
    	return "Uri = " + mUri + "\n";
    }
}
